#include <glib.h>

typedef struct my_data_tag {
    int id;
    char *name;
}my_data_t;

static void hook_func (gpointer data)
{
    my_data_t *d = (my_data_t *)data;
    g_print("(hook_func)data->id:%d, data->name:%s \n", d->id, d->name);
}

static void hook_destroy (gpointer data)
{
    my_data_t *d = (my_data_t *)data;
    if(NULL != d) {
        if(NULL != d->name) {
            g_print("(hook_destroy) %s \n", d->name);
            g_free(d->name);
        }
        g_free(d);
    }
}

static void test_glib_ghook (void)
{
    GHookList *hl;
    GHook *hook1, *hook2, *hook3;
    my_data_t *d1, *d2, *d3;

    d1 = g_new(my_data_t, 1);
    d1->id = 100;
    d1->name = g_strdup_printf("name-%d", d1->id);

    d2 = g_new(my_data_t, 1);
    d2->id = 200;
    d2->name = g_strdup_printf("name-%d", d2->id);

    d3 = g_new(my_data_t, 1);
    d3->id = 300;
    d3->name = g_strdup_printf("name-%d", d3->id);

    hl = g_new (GHookList, 1);
    g_hook_list_init (hl, sizeof (GHook));

    hook1 = g_hook_alloc (hl);
    hook1->data = d1;
    hook1->func = hook_func;
    hook1->flags = G_HOOK_FLAG_ACTIVE;
    hook1->destroy = hook_destroy;
    g_hook_append (hl, hook1);

    hook2 = g_hook_alloc (hl);
    hook2->data = d2;
    hook2->func = hook_func;
    hook2->flags = G_HOOK_FLAG_ACTIVE;
    hook2->destroy = hook_destroy;
    g_hook_append (hl, hook2);

    hook3 = g_hook_alloc (hl);
    hook3->data = d3;
    hook3->func = hook_func;
    hook3->flags = G_HOOK_FLAG_ACTIVE;
    hook3->destroy = hook_destroy;
    g_hook_append (hl, hook3);

    g_hook_list_invoke (hl, TRUE);

    g_print("after invoke: data1->id:%d, data1->name:%s \n", \
    ((my_data_t *)(hook1->data))->id, ((my_data_t *)(hook1->data))->name);
    g_print("after invoke: data2->id:%d, data2->name:%s \n", \
    ((my_data_t *)(hook2->data))->id, ((my_data_t *)(hook2->data))->name);
    g_print("after invoke: data3->id:%d, data3->name:%s \n", \
    ((my_data_t *)(hook3->data))->id, ((my_data_t *)(hook3->data))->name);

    g_print("destroy hook: %d \n", hook2->hook_id);
    g_hook_destroy(hl, hook2->hook_id);

    g_print("destroy_link hook: %d \n", hook1->hook_id);
    g_hook_destroy_link(hl, hook1);

    g_print("clear list! \n");
    g_hook_list_clear (hl);
    g_free (hl);
}


int main(int argc, char **argv) 
{
    test_glib_ghook();

    return 0;
}
